namespace SharpTalk.Core.Extensions
{
    using System;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Reflection;
    using Enums;


    public static class ExtensionMethods
    {
        /// <summary>
        /// Converts an expression into a <see cref="MemberInfo"/>.
        /// </summary>
        /// <param name="expression">The expression to convert.</param>
        /// <returns>The member info.</returns>
        public static MemberInfo GetMemberInfo(this Expression expression)
        {
            var lambda = (LambdaExpression)expression;
            MemberExpression memberExpression;

            if (lambda.Body is UnaryExpression)
            {
                var unaryExpression = (UnaryExpression)lambda.Body;
                memberExpression = (MemberExpression)unaryExpression.Operand;
            }
            else memberExpression = (MemberExpression)lambda.Body;

            return memberExpression.Member;
        }
       
        /// <summary>
        /// Checks the equality of two arrays of type T
        /// </summary>
        /// <returns>True if equals otherwise False</returns>
        public static bool Equals<T>(this T[] array, T[] other)
        {
            if(array == null && other == null) return true;
            if((array == null || other == null) || array.Length != other.Length ) return false;
            return array.SequenceEqual(other);
        }
        /// <summary>
        /// Determines if two UserStatusEnum values are equals.
        /// </summary>
        /// <returns>True if equals or both null otherwise false</returns>
        public static bool Equals(this UserStatusEnum first, UserStatusEnum second)
        {
            if (!Enum.IsDefined(typeof(UserStatusEnum), first) && !Enum.IsDefined(typeof(UserStatusEnum), second))
                return true;
            if (!Enum.IsDefined(typeof(UserStatusEnum), first) || !Enum.IsDefined(typeof(UserStatusEnum), second))
                return false;
            return first == second;
        }

        /// <summary>
        /// Checks the Equality of a <see cref="T:SharpTalk.Core.User"/>.
        /// </summary>
        /// <param name="user">The <see cref="T:SharpTalk.Core.User"/> to check.</param>
        /// <param name="firstname">The string to test against the User.FirstName property</param>
        /// <param name="lastName">The string to test against the User.LastName property</param>
        /// <param name="nickname">The string to test against the User.NickName property</param>
        /// <param name="uri">The string to test against the User.Uri property</param>
        /// <param name="image">The string to test against the User.Image property</param>
        /// <param name="status">The string to test against the User.status property</param>
        /// <returns>True if all properties are equal otherwise False</returns>
        public static bool Equals(this User user, string firstname, string lastName, string nickname, string uri, byte[] image, UserStatusEnum status)
        {
            return Equals(user.Status, status) &&
                   string.Equals(user.FirstName, firstname, StringComparison.InvariantCultureIgnoreCase) &&
                   string.Equals(user.LastName, lastName, StringComparison.InvariantCultureIgnoreCase) &&
                   string.Equals(user.NickName, nickname, StringComparison.InvariantCultureIgnoreCase) &&
                   string.Equals(user.Uri, uri, StringComparison.InvariantCultureIgnoreCase) &&
                   Equals(user.Image, image);

        }
        /// <summary>
        /// Checks User details validity
        /// </summary>
        /// <param name="user">the user instance to check</param>
        /// <returns>True if valid otherwise false</returns>
        public static bool IsValid(this User user)
        {
            return user != null &&
                   user.Guid != Guid.Empty &&
                   !(string.IsNullOrEmpty(user.FirstName) &&
                    string.IsNullOrEmpty(user.LastName) &&
                    string.IsNullOrEmpty(user.NickName));
        }
    }
}